<?php

class Template
{
	private $template;
	private $context;
	private $extends;
	
	public function __construct($tmpl_filename, TemplateContext $context)
	{
		$this->template = TemplateLoader::form_full_template_filename(
			$tmpl_filename);
		
		// Validate template exists
		if (!file_exists($this->template) || !is_readable($this->template))
			 throw new TemplateDoesNotExistException();
		
		$this->context = $context;
		$this->extends = NULL;
	}
	
	// Render with all extends, etc. which are recursive
	private function recursive_render()
	{
		$t = $this;
		$c = $this->context;
		
		// Buffer the output, and then store the variable in $response
		ob_start();
		require($t->template);
		$response = ob_get_contents();
		ob_end_clean();
		
		if (!is_null($this->extends))
		{
			$c->set_child_body($response);
			$parent = new Template($this->extends, $c);
			$response = $parent->render_to_string();
		}
		
		return $response;
	}
	
	public function render()
	{
		return new Response($this->recursive_render());
	}
	
	public function render_to_string()
	{
		return $this->recursive_render();
	}
	
	public function extend($tmpl_filename)
	{
		if (!is_null($this->extends))
		{
			// This has already been called once
			throw new MethodCalledTwiceException();
		}
		
		$this->extends = $tmpl_filename;
	}
	
	public function partial($tmpl_filename, array $options=NULL)
	{
		$c = TemplateContext::merge($this->context,
			new TemplateContext($options?:array()));
		$t = new Template($tmpl_filename, $c);
		$r = $t->render_to_string();
		return $r;
	}
	
	public function partial_collection($tmpl_filename, array $collection)
	{
		$total = '';
		foreach ($collection as $item)
		{
			$total .= $this->partial($tmpl_filename, array('item' => $item));
		}
		return $total;
	}
}

?>